package com.android.test.activity;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.gesture.GestureOverlayView;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.ViewFlipper;

import com.android.test.R;
import com.android.test.dialog.LoadingDialog;
import com.android.test.model.BaiduSearchListener;
import com.android.test.model.OrgDetailInfo;
import com.android.test.model.OrgSearchResultAdapter;
import com.android.test.util.Constants;
import com.android.test.util.DataUtils;
import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.GeoPoint;
import com.baidu.mapapi.LocationListener;
import com.baidu.mapapi.MKLocationManager;
import com.baidu.mapapi.MKPlanNode;
import com.baidu.mapapi.MKSearch;
import com.baidu.mapapi.MapActivity;
import com.baidu.mapapi.MapController;
import com.baidu.mapapi.MapView;
import com.baidu.mapapi.MyLocationOverlay;
import com.baidu.mapapi.Overlay;
import com.baidu.mapapi.RouteOverlay;
import com.baidu.mapapi.TransitOverlay;

public class SearchActivity extends MapActivity implements LocationListener{

	private final String TAG = getClass().getSimpleName();
	private final static int DIALOG_PROGRESS_SEARCH_NEARBY = 1;
	private final static int DIALOG_PROGRESS_SEARCH_LOCATION = 2;
	private final static int SEARCH_COUNT_MAX = 3;
	private final static int NUM_TRANSIT_PLAN_SHOW = 3;
	private static final int MSG_REQUEST_SEARCH = 100;
	private static final int MSG_SEARCH_FAILED = MSG_REQUEST_SEARCH + 1;
	private static final int MSG_SEARCH_FINISHED = MSG_SEARCH_FAILED + 1;
	private static final int MSG_REMOVE_PROGRESS_DIALOG = MSG_SEARCH_FINISHED + 1;
	private static final int MSG_LOCATION_CHANGED = MSG_REMOVE_PROGRESS_DIALOG+1;
	private static final int MSG_GET_TRANSIT_RESULT = MSG_LOCATION_CHANGED+1;
	private static final int MSG_GET_DRIVINT_RESULT = MSG_GET_TRANSIT_RESULT+1;
	private static final int MSG_GET_WALKING_RESULT = MSG_GET_DRIVINT_RESULT+1;
	private static final int MSG_SEARCH_DRIVING_REQUEST = MSG_GET_WALKING_RESULT+1;
	private static final int MSG_SEARCH_WALKING_REQUEST = MSG_SEARCH_DRIVING_REQUEST+1;
	
	private static final int LEVEL_MAP_ZOOM = 12;
	enum SearchMode{
			Org,
			Subject,
			Keywords
        };
    
    enum SearchResultType{
    		Transit,
    		Driving,
    		Walking
    	};
    	
    private LinearLayout mSearchBar;
    private LinearLayout mLayoutSpinner;
	private Spinner mSearchSpinner;
	private ListView mSearchListView;
	private ListView mSearchResultListView;
	private EditText mSearchEditText;
	private Button mSearchButton;
	private ViewFlipper mViewFlipper;
	private GestureOverlayView mGestureOverlayView;
/*	private PlaylistRemote[] mPlaylistRemotes = null;*/
	private SearchMode mSearchMode;

	//for search organism
	private BMapManager mapManager = null;
	private MapView mMapView = null;
	private MapController mMapController;
	private MKSearch mMKSearch = null;
	private BaiduSearchListener mSearchListener = null;
	private MKLocationManager mLocationManager = null;
	private GeoPoint mCurLocation = null;
	private CountDownTimer mTimer = null;
	private OrgSearchResultAdapter mSearchResultAdapter = null;
	private InputMethodManager imm;
	private boolean mSearchFinished = true;
	private boolean bRegisted = false;
	private boolean mLocationChanged = false;
	private int mSearchCount = 0;
	private int mCurDialogId = -1;
	private int mCurKeyIndex = 0;
	private int mKeyWordsCount = 0;
	private String mInputString = null;
	private String[] keyArray = null;
	private String mCurCity = "北京";
	//overlays 
	private MyLocationOverlay mMyLocation;
	private GeoPoint mTmpLocation;
	public static void launch(Context c){
		Intent intent = new Intent(c, SearchActivity.class);
		c.startActivity(intent);
	}

	/** Called when the activity is first created. */
	@SuppressWarnings("unchecked")
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_search);
/*		mGestureOverlayView.addOnGesturePerformedListener(JamendoApplication
				.getInstance().getPlayerGestureHandler());*/
		findViews();
		initViews();
		initBaiduMap();
	}

	private void findViews(){
		mSearchBar = (LinearLayout) findViewById(R.id.layout_search_bar);
		mLayoutSpinner = (LinearLayout) findViewById(R.id.layout_spinner);
		mSearchSpinner = (Spinner)findViewById(R.id.SearchSpinner);
		mSearchButton = (Button)findViewById(R.id.SearchButton);
		mSearchEditText = (EditText)findViewById(R.id.SearchEditText);
		mSearchListView = (ListView)findViewById(R.id.SearchListView);
		mSearchResultListView=(ListView)findViewById(R.id.searchresultlist);
		mViewFlipper = (ViewFlipper)findViewById(R.id.SearchViewFlipper);
		mGestureOverlayView = (GestureOverlayView) findViewById(R.id.gestures);
		mMapView = (MapView)findViewById(R.id.map_View);
	}
	
	private void initViews(){
		imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		ArrayAdapter adapter = ArrayAdapter.createFromResource(
				this, R.array.search_modes, android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mSearchButton.setOnClickListener(mSearchButtonListener);
		mSearchSpinner.setAdapter(adapter);
		if(mSearchListView.getCount() == 0){
			mViewFlipper.setDisplayedChild(2); // search list hint
		}
		mMapView.setTraffic(true);
        mMapView.setBuiltInZoomControls(true); 
		mSearchResultListView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				if(mSearchResultAdapter!=null){
					mSearchResultAdapter.toggle(position);
				}
			}
		});
		mSearchResultListView.setOnItemLongClickListener(new OnItemLongClickListener() {

			@Override
			public boolean onItemLongClick(AdapterView<?> parent, View view,
					int position, long id) {
				mSearchBar.setVisibility(View.GONE);
				mLayoutSpinner.setVisibility(View.GONE);
				mMapView.setVisibility(View.VISIBLE);
				mMapView.setBuiltInZoomControls(true);
				mTmpLocation = DataUtils.mOrgPoiInfo.get(position).mGpoint;
				if(mTmpLocation!=null){
					findTransit(mCurLocation, mTmpLocation,mCurCity,MKSearch.EBUS_TRANSFER_FIRST);
				}
				return false;
			}
		});
		keyArray = getResources().getStringArray(R.array.org_keywords);
		if(keyArray!=null){
			mKeyWordsCount = keyArray.length;
		}
		mSearchSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
			@Override
			public void onItemSelected(AdapterView<?> parent, View view,
					int position, long id) {
				switch(position){
					case 0:
						mSearchMode = SearchMode.Org;
						break;
					case 1:
						break;
					case 2:
						break;
				}
			}

			@Override
			public void onNothingSelected(AdapterView<?> parent) {
			}
		});
	}
	
	/**
	 * 收起软键盘并设置提示文字
	 */
	public void collapseSoftInputMethod(){
		if(TextUtils.isEmpty(mSearchEditText.getText().toString())){
			mSearchEditText.setHint(R.string.search_hint);
		}
		mSearchEditText.clearFocus();
		if(imm!=null){
			imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
		}
	}
	
	/***********************************************************
	 * 
	 * init baidu map api
	 * 
	 * @param
	 * 
	 * @return
	 * 
	 **********************************************************/
	private void initBaiduMap(){
		mapManager = new BMapManager(this);
		// the BAIDU map key
		if (!mapManager.init(Constants.KEY_MAP_BAIDU, null)) {
			Log.e(TAG, "mapManager.init failed");
			return;
		}
		if (!super.initMapActivity(mapManager)) {
			Log.e(TAG, "initMapActivity failed");
			return;
		}
		if (mapManager != null) {
			// initial location module
			mLocationManager = mapManager.getLocationManager();
			if (mLocationManager != null){
				// 通过enableProvider和disableProvider方法，选择定位的Provider
				mLocationManager.enableProvider(MKLocationManager.MK_NETWORK_PROVIDER);
				mLocationManager.disableProvider(MKLocationManager.MK_GPS_PROVIDER);
				mLocationManager.requestLocationUpdates(this);
			}
			mapManager.start();
		}
		mSearchListener = new BaiduSearchListener(this);
		if (mMKSearch == null) {
			mMKSearch = new MKSearch();
			if (mMKSearch == null) {
				Log.e(TAG, "new MKSearch failed");
				return;
			}
			if (!mMKSearch.init(mapManager, mSearchListener)) {
				Log.e(TAG, "mMKSearch.init failed");
				return;
			}
		}
		
		mMapController = mMapView.getController();
		mMapController.setZoom(LEVEL_MAP_ZOOM);
	}

	@Override
	public void onBackPressed() {
		if(mMapView.isShown()){
			mMapView.setVisibility(View.GONE);
			mSearchBar.setVisibility(View.VISIBLE);
			mLayoutSpinner.setVisibility(View.VISIBLE);
			removeTransitOverLays();
			removeRouteOverLays();
			return;
		}
		super.onBackPressed();
	}

	@Override
	protected void onResume() {
		super.onResume();
		boolean gesturesEnabled = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("gestures", true);
		mGestureOverlayView.setEnabled(gesturesEnabled);
		registReceivers();
		if (mapManager != null) {
			mapManager.start();
			Log.e(TAG, "start mapmanager onResume");
		}
		if (!mSearchFinished) {
			resetSearch();
			Log.e(TAG, "Reset search environment");
		}
	}
	
	private void registReceivers(){
		if (!bRegisted) {
			IntentFilter filter = new IntentFilter();
			filter.addAction(Constants.ACTION_POI_RESULT);
			filter.addAction(Constants.ACTION_TRANSIT_RESULT);
			filter.addAction(Constants.ACTION_DRIVING_RESULT);
			filter.addAction(Constants.ACTION_WALKING_RESULT);
			registerReceiver(mReceiver, filter);
			bRegisted = !bRegisted;
			Log.e(TAG, "Regist recevier");
		}
	}
	
	private void unRegistReceivers(){
		if (bRegisted) {
			unregisterReceiver(mReceiver);
			bRegisted = !bRegisted;
			Log.e(TAG, "Unregist recevier");
		}
	}
	
	private BroadcastReceiver mReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().endsWith(Constants.ACTION_POI_RESULT)) {
				Log.e(TAG, "Receive Search result coming");
				if (mSearchFinished) {
					Log.e(TAG, "Search has finished");
					return;
				}
				final boolean hasResult = intent.getBooleanExtra(
						Constants.KEY_POI_SEARCH_STATUS, true);
				Log.e(TAG,"hasResult = "+hasResult);
				if(hasResult){
					if(mCurKeyIndex<mKeyWordsCount-1&&TextUtils.isEmpty(mInputString)){
						if(mSearchResultAdapter!=null){
							mSearchResultAdapter.initExpandedState();
							mSearchResultAdapter.notifyDataSetChanged();
						}
						searchNextKeyWord();
					}else{
						mHandler.sendEmptyMessage(MSG_SEARCH_FINISHED);
					}
				}else{
					//current search has failed, try again
					resetSearchTimer();
					mHandler.sendEmptyMessage(MSG_REQUEST_SEARCH);
					return;
				}
			}else if(intent.getAction().endsWith(Constants.ACTION_TRANSIT_RESULT)){
				Log.e(TAG,"receive transit result");
				final boolean hasResult = intent.getBooleanExtra(
						Constants.KEY_TRANSIT_SEARCH_STATUS, true);
				Log.e(TAG,"hasResult = "+hasResult);
				if(hasResult){
					if(DataUtils.mTransitRouteResult==null){
						Log.e(TAG,"DataUtils.mTransitRouteResult is null, get transit plan failed");
						mHandler.sendEmptyMessage(MSG_SEARCH_DRIVING_REQUEST);
						return;
					}
					mHandler.sendEmptyMessage(MSG_GET_TRANSIT_RESULT);
				}else{
					Log.e(TAG,"find transit plan failed,try to find driving route now");
					mHandler.sendEmptyMessage(MSG_SEARCH_DRIVING_REQUEST);
					DataUtils.mTransitRouteResult = null;
				}
			}else if(intent.getAction().endsWith(Constants.ACTION_DRIVING_RESULT)){
				Log.e(TAG,"receive driving route result");
				final boolean hasResult = intent.getBooleanExtra(
						Constants.KEY_DRIVING_SEARCH_STATUS, true);
				Log.e(TAG,"hasResult = "+hasResult);
				if(hasResult){
					if(DataUtils.mDrivingRouteResult==null){
						Log.e(TAG,"DataUtils.mDrivingRouteResult is null, get driving route failed");
						mHandler.sendEmptyMessage(MSG_SEARCH_WALKING_REQUEST);
						return;
					}
					mHandler.sendEmptyMessage(MSG_GET_DRIVINT_RESULT);
				}else{
					Log.e(TAG,"find driving route failed,try to find walking route now");
					mHandler.sendEmptyMessage(MSG_SEARCH_WALKING_REQUEST);
					DataUtils.mDrivingRouteResult = null;
				}
			}else if(intent.getAction().endsWith(Constants.ACTION_WALKING_RESULT)){
				Log.e(TAG,"receive walking route result");
				final boolean hasResult = intent.getBooleanExtra(
						Constants.KEY_WALKING_SEARCH_STATUS, true);
				Log.e(TAG,"hasResult = "+hasResult);
				if(hasResult){
					if(DataUtils.mWalkingRouteResult==null){
						Log.e(TAG,"DataUtils.mWalkingRouteResult is null, get walking route failed");
						return;
					}
					mHandler.sendEmptyMessage(MSG_GET_WALKING_RESULT);
				}else{
					Log.e(TAG,"find walking route failed");
					mTmpLocation = null;
					DataUtils.mWalkingRouteResult = null;
				}
			}			
		}
	};
	
	private void removeTransitOverLays(){
		List<Overlay> overlayList = mMapView.getOverlays();
        int overlayCount = overlayList.size();
        for(int i=0;i<overlayCount;i++){
        	final Overlay overlay = overlayList.get(i);
        	if(overlay instanceof TransitOverlay){
        		mMapView.getOverlays().remove(overlay);
        		i--;
        		overlayCount--;
        	}
        }
	}
	
	private void removeRouteOverLays(){
		List<Overlay> overlayList = mMapView.getOverlays();
        int overlayCount = overlayList.size();
        for(int i=0;i<overlayCount;i++){
        	final Overlay overlay = overlayList.get(i);
        	if(overlay instanceof RouteOverlay){
        		mMapView.getOverlays().remove(overlay);
        		i--;
        		overlayCount--;
        	}
        }
	}
	
	private void removeMyLocation(){
		List<Overlay> overlayList = mMapView.getOverlays();
        int overlayCount = overlayList.size();
        for(int i=0;i<overlayCount;i++){
        	final Overlay overlay = overlayList.get(i);
        	if(overlay instanceof MyLocationOverlay){
        		mMapView.getOverlays().remove(overlay);
        		i--;
        		overlayCount--;
        	}
        }
	}
	
	private void searchPoiInfoByKeyWords(String keyword){
		Log.e(TAG, "KeyWord="+keyword);
		if (mSearchCount >= SEARCH_COUNT_MAX) {
			if(mCurKeyIndex<mKeyWordsCount-1&&TextUtils.isEmpty(mInputString)){
				searchNextKeyWord();
				return;
			}
			mHandler.sendEmptyMessage(MSG_SEARCH_FAILED);
			Log.e(TAG, "Search failed");
			return;
		}
		if(null==DataUtils.mOrgPoiInfo){
			DataUtils.mOrgPoiInfo = new ArrayList<OrgDetailInfo>();
		}else if(mCurKeyIndex==0&&mSearchCount==0){
			DataUtils.mOrgPoiInfo.clear();
			if(mSearchResultAdapter!=null){
				mSearchResultAdapter.initExpandedState();
				mSearchResultAdapter.notifyDataSetChanged();
			}
		}
		if (null == mSearchListener) {
			mSearchListener = new BaiduSearchListener(this);
		}
		int result = -1;
		try {
			if (mMKSearch == null) {
				mMKSearch = new MKSearch();
				if (mMKSearch == null) {
					Log.e(TAG, "new MKSearch failed");
					return;
				}
				if (!mMKSearch.init(mapManager, mSearchListener)) {
					Log.e(TAG, "mMKSearch.init failed");
					return;
				}
			}
			if (mSearchFinished) {
				mSearchFinished = !mSearchFinished;
				mCurDialogId = DIALOG_PROGRESS_SEARCH_NEARBY;
				showDialog(mCurDialogId);
			}
//			MKSearch.setPoiPageCapacity(6);
			result = mMKSearch.poiSearchNearBy(keyword, mCurLocation, Constants.SEARCH_DISTANCE);
			//阳光喔作文培训
			//result = mMKSearch.poiSearchNearBy(keyword, new GeoPoint(23126162, 113295258), SEARCH_DISTANCE);
			//昂立少儿教育
			//result = mMKSearch.poiSearchNearBy(keyword, new GeoPoint(31273637, 121548396), SEARCH_DISTANCE);
			mSearchCount++;
			Log.e(TAG, "mSearchCount=" + mSearchCount);
			startSearchTimer();
		} catch (Exception e) {
			e.printStackTrace();
			Log.e(TAG, "Search has failed");
		}
		if (result == -1) {
			Log.e(TAG, "poiSearchNearBy Search has failed");
		}
	}
	
	  /** 
     * 设置公交换乘路线搜索策略，有以下4种策略可选择： 
     *    1）不含地铁：MKSearch.EBUS_NO_SUBWAY 
     *    2）时间优先：MKSearch.EBUS_TIME_FIRST 
     *    3）最少换乘：MKSearch.EBUS_TRANSFER_FIRST  
     *    4）最少步行距离：MKSearch.EBUS_WALK_FIRST 
     * 我们这里选择的搜索策略是最少换乘，即中途转车次数最少 
     * mMKSearch.setTransitPolicy(MKSearch.EBUS_TRANSFER_FIRST);  
     * //必须要设置在哪个城市搜索  
     * mMKSearch.transitSearch("贵阳", startPlanNode, endPlanNode); 
     */
	private void findTransit(GeoPoint start,GeoPoint end,String city, int searchPolicy){
		Log.e(TAG,"findTransit called");
		MKPlanNode startPlanNode = new MKPlanNode();
		startPlanNode.pt = start;
		MKPlanNode endPlanNode = new MKPlanNode();
		endPlanNode.pt=end;
		int result = -1;
		try{
			if (null == mSearchListener) {
				mSearchListener = new BaiduSearchListener(this);
			}
			if (mMKSearch == null) {
				mMKSearch = new MKSearch();
				if (mMKSearch == null) {
					Log.e(TAG, "new MKSearch failed");
					return;
				}
				if (!mMKSearch.init(mapManager, mSearchListener)) {
					Log.e(TAG, "mMKSearch.init failed");
					return;
				}
			}
			mMKSearch.setTransitPolicy(searchPolicy);
			Log.e(TAG,"Search transit begin");
			result = mMKSearch.transitSearch(city, startPlanNode, endPlanNode);
		}catch(Exception e) {
			e.printStackTrace();
			Log.e(TAG, "Search has failed");
		}
		if (result == -1) {
			Log.e(TAG, "transitSearch has failed");
		}
	}
	
	private void findDrivingRoute(GeoPoint start,GeoPoint end,int searchPolicy){
		Log.e(TAG,"findDrivingRoute called");
		MKPlanNode startPlanNode = new MKPlanNode();
		startPlanNode.pt = start;
		MKPlanNode endPlanNode = new MKPlanNode();
		endPlanNode.pt=end;
		int result = -1;
		try{
			if (null == mSearchListener) {
				mSearchListener = new BaiduSearchListener(this);
			}
			if (mMKSearch == null) {
				mMKSearch = new MKSearch();
				if (mMKSearch == null) {
					Log.e(TAG, "new MKSearch failed");
					return;
				}
				if (!mMKSearch.init(mapManager, mSearchListener)) {
					Log.e(TAG, "mMKSearch.init failed");
					return;
				}
			}
			mMKSearch.setTransitPolicy(searchPolicy);
			Log.e(TAG,"Search DrivingRoute begin");
			result = mMKSearch.drivingSearch(null, startPlanNode, null, startPlanNode);
		}catch(Exception e) {
			e.printStackTrace();
			Log.e(TAG, "Search has failed");
		}
		if (result == -1) {
			Log.e(TAG, "drivingSearch has failed");
		}
	}
	
	private void findWalkingRoute(GeoPoint start,GeoPoint end,int searchPolicy){
		Log.e(TAG,"findWalkingRoute called");
		MKPlanNode startPlanNode = new MKPlanNode();
		startPlanNode.pt = start;
		MKPlanNode endPlanNode = new MKPlanNode();
		endPlanNode.pt=end;
		int result = -1;
		try{
			if (null == mSearchListener) {
				mSearchListener = new BaiduSearchListener(this);
			}
			if (mMKSearch == null) {
				mMKSearch = new MKSearch();
				if (mMKSearch == null) {
					Log.e(TAG, "new MKSearch failed");
					return;
				}
				if (!mMKSearch.init(mapManager, mSearchListener)) {
					Log.e(TAG, "mMKSearch.init failed");
					return;
				}
			}
			mMKSearch.setTransitPolicy(searchPolicy);
			Log.e(TAG,"Search WalkingRoute begin");
			result = mMKSearch.walkingSearch(null, startPlanNode, null, startPlanNode);
		}catch(Exception e) {
			e.printStackTrace();
			Log.e(TAG, "Search has failed");
		}
		if (result == -1) {
			Log.e(TAG, "walkingSearch has failed");
		}
	}

	private void searchFinished() {
		Log.e(TAG, "search finished");
		resetSearch();
		resetSearchTimer();
	}
	
	private void resetSearch() {
		mInputString = null;
		mSearchCount = 0;
		mCurKeyIndex = 0;
		mSearchFinished = true;
		mHandler.sendEmptyMessage(MSG_REMOVE_PROGRESS_DIALOG);
	}
	
	private void startSearchTimer() {
		mTimer = new CountDownTimer(Constants.TIME_OUT_COUNT_SEARTCH, 1000) {
			public void onTick(long millisUntilFinished) {
			}

			public void onFinish() {
				// search timeout we kill it
				Log.e(TAG, "Search timeout");
				mHandler.sendEmptyMessage(MSG_SEARCH_FAILED);
			}
		}.start();
	}

	private void resetSearchTimer() {
		if (mTimer != null) {
			mTimer.cancel();
			mTimer = null;
		}
	}
	
	@Override
	protected void onStop() {
		unRegistReceivers();
		if (mapManager != null) {
			mapManager.stop();
			Log.e(TAG, "stop mapmanager onStop");
		}
		if (!mSearchFinished) {
			resetSearchTimer();
			Log.e(TAG, "cancel search timer onStop");
		}
		super.onStop();
	}
	
	@Override
	protected void onDestroy() {
		unRegistReceivers();
		if (mapManager != null) {
			mapManager.destroy();
			mapManager = null;
		}
		if (!mSearchFinished) {
			resetSearchTimer();
			Log.e(TAG, "cancel search timer onDestroy");
		}
		super.onDestroy();
	}
	
	private void searchNextKeyWord(){
		Log.e(TAG,"searchNextKeyWord called");
		mCurKeyIndex++;
		Log.e(TAG, "mCurKeyIndex="+mCurKeyIndex);
		mSearchCount = 0;
		resetSearchTimer();
		mHandler.sendEmptyMessage(MSG_REQUEST_SEARCH);
	}
	
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MSG_REQUEST_SEARCH: {
					if(TextUtils.isEmpty(mInputString)){
						searchPoiInfoByKeyWords(keyArray[mCurKeyIndex]);
					}else{
						Log.e(TAG, "Search by input");
						searchPoiInfoByKeyWords(mInputString);
					}
				}
				break;
			case MSG_SEARCH_FAILED: {
					if(mCurKeyIndex<mKeyWordsCount-1&&TextUtils.isEmpty(mInputString)){
						if(mSearchCount<SEARCH_COUNT_MAX){
							mHandler.sendEmptyMessage(MSG_REQUEST_SEARCH);
							return;
						}
						searchNextKeyWord();
					}else{
						searchFinished();
						dialogShowMessage(R.string.title_tip_dialog, getResources()
								.getString(R.string.msg_search_failed));
					}
				}
				break;
			case MSG_REMOVE_PROGRESS_DIALOG: {
					if (mSearchFinished) {
						removeDialog(mCurDialogId);
						mCurDialogId = -1;
					}
				}
				break;
			case MSG_SEARCH_FINISHED: {
					Log.e(TAG,"receive search success result");
					searchFinished();
					if(mSearchResultAdapter==null){
						mSearchResultAdapter = new OrgSearchResultAdapter(SearchActivity.this, DataUtils.mOrgPoiInfo);
						mSearchResultAdapter.initExpandedState();
						mSearchResultListView.setAdapter(mSearchResultAdapter);
					}else{
						mSearchResultAdapter.initExpandedState();
						mSearchResultAdapter.notifyDataSetChanged();
					}
				}
				break;
			case MSG_LOCATION_CHANGED:{
				mMapController.setCenter(mCurLocation);
		        removeMyLocation();
		        mMyLocation = null;
				mMyLocation = new MyLocationOverlay(SearchActivity.this, mMapView);
				mMyLocation.enableMyLocation(); // 启用定位
				mMyLocation.enableCompass();    // 启用指南针
				mMapView.getOverlays().add(mMyLocation);
//				getAddressbyGeoPoint(mCurLocation);
				}
				break;
			case MSG_GET_TRANSIT_RESULT:{
				/** TransitOverlay是baidu map api提供的用于在地图上显示公交换乘路线的Overlay  
		        TransitOverlay transitOverlay = new TransitOverlay(TransitPolicyActivity.this, mapView);  
		        // 展示其中一个换乘方案  
		        transitOverlay.setData(result.getPlan(0));  
		        // 在地图上显示  
		        mapView.getOverlays().add(transitOverlay);  
		         * 如果需要在地图上展示所有公交换乘方案，请将165-170行注释，并打开注释行176-186 
		         * 但由于通常返回的公交换乘方案数较多，全显示在地图上会很乱，可能分辨不出来,所以只显示了其中一种方案 
		        TransitOverlay transitOverlay = null; 
		        // 遍历搜索结果，得到所有换乘方案 
		        for(int i=0; i<result.getNumPlan(); i++) { 
		            transitOverlay = new TransitOverlay(TransitPolicyActivity.this, mapView); 
		            // 设置展示数据 
		            transitOverlay.setData(result.getPlan(i)); 
		            // 在地图上显示 
		            mapView.getOverlays().add(transitOverlay); 
		        } 
		         * 说明： 
		         *      1）公交换乘路线搜索结果通常都有多种换乘方案; 
		         *      2）通过result.getNumPlan()可以得到换乘方案数。 
		         * 除了在地图上标注其中一种公交换乘方案外，如果我们要得到所有换乘方案的信息，就需要像下面这样遍历搜索结果 
		         */  
					int planCount =  DataUtils.mTransitRouteResult.getNumPlan();
					if(planCount>NUM_TRANSIT_PLAN_SHOW){
						planCount = NUM_TRANSIT_PLAN_SHOW;
					}
			        for(int i=0; i<planCount; i++) {  
			            TransitOverlay transitOverlay = new TransitOverlay(SearchActivity.this, mMapView);  
				        transitOverlay.setData(DataUtils.mTransitRouteResult.getPlan(i));  
				        mMapView.getOverlays().add(transitOverlay);  
			        } 
			        mMapController.animateTo(mTmpLocation);
			        DataUtils.mTransitRouteResult = null;
			        mTmpLocation = null;
				}
				break;
			case MSG_GET_DRIVINT_RESULT:{
					int planCount =  DataUtils.mDrivingRouteResult.getNumPlan();
					if(planCount>NUM_TRANSIT_PLAN_SHOW){
						planCount = NUM_TRANSIT_PLAN_SHOW;
					}
			        for(int i=0; i<planCount; i++) {  
			            RouteOverlay routeOverlay = new RouteOverlay(SearchActivity.this, mMapView);  
			            routeOverlay.setData(DataUtils.mDrivingRouteResult.getPlan(i).getRoute(0));  
				        mMapView.getOverlays().add(routeOverlay);  
			        } 
			        mMapController.animateTo(mTmpLocation);
			        DataUtils.mDrivingRouteResult = null;
			        mTmpLocation = null;
				}
				break;
			case MSG_GET_WALKING_RESULT:{
					int planCount = DataUtils.mWalkingRouteResult.getNumPlan();
					if(planCount>NUM_TRANSIT_PLAN_SHOW){
						planCount = NUM_TRANSIT_PLAN_SHOW;
					}
			        for(int i=0; i<planCount; i++) {  
			        	RouteOverlay routeOverlay = new RouteOverlay(SearchActivity.this, mMapView);  
			            routeOverlay.setData(DataUtils.mWalkingRouteResult.getPlan(i).getRoute(0));  
				        mMapView.getOverlays().add(routeOverlay);  
			        } 
			        mMapController.animateTo(mTmpLocation);
			        DataUtils.mWalkingRouteResult = null;
			        mTmpLocation = null;
				}
				break;
			case MSG_SEARCH_DRIVING_REQUEST:
				findDrivingRoute(mCurLocation, mTmpLocation, MKSearch.EBUS_TIME_FIRST);
				break;
			case MSG_SEARCH_WALKING_REQUEST:
				findWalkingRoute(mCurLocation, mTmpLocation, MKSearch.EBUS_TIME_FIRST);
				break;
			}
		}
	};
	
	private String getAddressbyGeoPoint(GeoPoint gp)
    {
       String strReturn = "";
       try
       {
          Geocoder gc = new Geocoder(SearchActivity.this, Locale.getDefault());
          List<Address> lstAddress =   gc.getFromLocation(
        		  gp.getLatitudeE6()/1000000f,
        		  gp.getLongitudeE6()/10000000f, 1);
          StringBuilder sb = new StringBuilder();
          if (lstAddress.size() > 0)
          {  
            Address adsLocation = lstAddress.get(0);
            sb.append(adsLocation.getLocality()).append("\n");
          }
          strReturn = sb.toString();
          Log.e(TAG, "strReturn="+strReturn);
      }catch(Exception e){
         e.printStackTrace();
      }
      return strReturn;
    }
	
	private void dialogShowMessage(int title, String msg) {
		new AlertDialog.Builder(SearchActivity.this)
			.setTitle(R.string.title_tip_dialog).setMessage(msg)
			.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			}).create().show();
	}
	
	/***********************************************************
	 * 
	 * Called when the user call showDialog
	 * 
	 * @param
	 * 
	 * @return
	 * 
	 **********************************************************/
	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_PROGRESS_SEARCH_NEARBY: {
			// create progress bar dialog
			ProgressDialog dialog = new ProgressDialog(this);
			dialog.setTitle(R.string.msg_wait);
			dialog.setMessage(getResources().getString(
					R.string.msg_search_nearby));
			dialog.setIndeterminate(false);
			return dialog;
		}
		case DIALOG_PROGRESS_SEARCH_LOCATION: {
			// create progress bar dialog
			final ProgressDialog dialog = new ProgressDialog(this);
			dialog.setTitle(R.string.msg_wait);
			dialog.setMessage(getResources().getString(
					R.string.msg_search_location));
			dialog.setIndeterminate(false);
			dialog.setCancelable(true);
			return dialog;
		}
		}
		return null;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		mSearchMode = (SearchMode) savedInstanceState.getSerializable("mode");
		if(mSearchMode != null){
			if(mSearchMode.equals(SearchMode.Org) 
					|| mSearchMode.equals(SearchMode.Subject)
					|| mSearchMode.equals(SearchMode.Keywords)){
/*				AlbumAdapter adapter = new AlbumAdapter(this);
				adapter.setList((ArrayList<Album>) savedInstanceState.get("values"));
				mSearchListView.setAdapter(adapter);
				mSearchListView.setOnItemClickListener(mAlbumClickListener);*/
			}
			
			if(mSearchMode.equals(SearchMode.Subject)) {
/*				PlaylistRemoteAdapter adapter = new PlaylistRemoteAdapter(this); 
				adapter.setList((ArrayList<PlaylistRemote>) savedInstanceState.get("values"));
				mSearchListView.setAdapter(adapter);
				mSearchListView.setOnItemClickListener(mPlaylistClickListener);*/
			}
			
			mViewFlipper.setDisplayedChild(savedInstanceState.getInt("flipper_page"));
		}
		super.onRestoreInstanceState(savedInstanceState);
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		if(mSearchMode != null){
			outState.putSerializable("mode", mSearchMode);
			if(mSearchMode.equals(SearchMode.Org) 
					|| mSearchMode.equals(SearchMode.Subject) 
					|| mSearchMode.equals(SearchMode.Keywords)){
/*				AlbumAdapter adapter = (AlbumAdapter)mSearchListView.getAdapter();
				outState.putSerializable("values", adapter.getList());*/
			}

			if(mSearchMode.equals(SearchMode.Subject)) {
/*				PlaylistRemoteAdapter adapter = (PlaylistRemoteAdapter)mSearchListView.getAdapter();
				outState.putSerializable("values", adapter.getList());*/
			}
			
			outState.putInt("flipper_page", mViewFlipper.getDisplayedChild());
		}
		super.onSaveInstanceState(outState);
	}

	private OnClickListener mSearchButtonListener = new OnClickListener(){

		public void onClick(View v) {
			mInputString = mSearchEditText.getText().toString();
//				new SearchingDialog(SearchActivity.this,
//						R.string.searching,
//						R.string.search_fail)
//				.execute(mSearchSpinner.getSelectedItemPosition());	
			if(mSearchFinished){
				mSearchEditText.setText("");
				collapseSoftInputMethod();
				mCurKeyIndex = 0;
				mHandler.sendEmptyMessage(MSG_REQUEST_SEARCH);
			}

		}
	};

	private OnItemClickListener mAlbumClickListener = new OnItemClickListener(){

		public void onItemClick(AdapterView<?> adapterView, View view, int position,
				long time) {
/*			Album album = (Album)adapterView.getItemAtPosition(position);
			PlayerActivity.launch(SearchActivity.this, album);*/
		}

	};

	private OnItemClickListener mPlaylistClickListener = new OnItemClickListener(){

		public void onItemClick(AdapterView<?> adapterView, View arg1, int position,
				long arg3) {
/*			PlaylistRemote playlistRemote = (PlaylistRemote) adapterView.getItemAtPosition(position);
			PlayerActivity.launch(SearchActivity.this, playlistRemote);*/
		}

	};

	private class SearchingDialog extends LoadingDialog<Integer, Integer>{

		private Integer mSearchMode;
		private BaseAdapter mAdapter;

		public SearchingDialog(Activity activity, int loadingMsg, int failMsg) {
			super(activity, loadingMsg, failMsg);
		}

		public Integer doInBackground(Integer... params) {
			mSearchMode = params[0];
			switch(mSearchMode){
			case 0:
				// artist search
//				albumSearch(0); 
				if(mSearchFinished){
					mHandler.sendEmptyMessage(MSG_REQUEST_SEARCH);
					mCurKeyIndex = 0;
				}
				break;
			case 1:
				// tag search
				albumSearch(1); 
				break;
			case 2:
				// playlist search
				playlistSearch(); 
				break;
			case 3:
				// starred album search
				albumSearch(3); 
				break;
			default:
			}
			return mSearchMode;
		}

		public void doStuffWithResult(Integer result) {
			mSearchListView.setAdapter(mAdapter);

			if(mSearchListView.getCount() > 0){
				mViewFlipper.setDisplayedChild(0); // display results
			} else {
				mViewFlipper.setDisplayedChild(1); // display no results message
			}

			// results are albums
			if(mSearchMode.equals(0) || mSearchMode.equals(1) ||  mSearchMode.equals(3)){
				mSearchListView.setOnItemClickListener(mAlbumClickListener);
			}

			// results are playlists
			if(mSearchMode.equals(2)){
				mSearchListView.setOnItemClickListener(mPlaylistClickListener);
			}
		}

		private void albumSearch(int id){
/*			JamendoGet2Api service = new JamendoGet2ApiImpl();
			String query = mSearchEditText.getText().toString();
			Album[] albums = null;
			try {
				switch (id) {
				case 0:
					albums = service.searchForAlbumsByArtist(query);
					SearchActivity.this.mSearchMode = SearchMode.Artist;
					break;
				case 1:
					albums = service.searchForAlbumsByTag(query);
					SearchActivity.this.mSearchMode = SearchMode.Tag;
					break;
				case 3:
					albums = service.getUserStarredAlbums(query);
					SearchActivity.this.mSearchMode = SearchMode.UserStarredAlbums;
					break;

				default:
					return;
				}

				AlbumAdapter albumAdapter = new AlbumAdapter(SearchActivity.this); 
				albumAdapter.setList(albums);
				albumAdapter.setListView(mSearchListView);
				mAdapter = albumAdapter;

			} catch (JSONException e) {
				e.printStackTrace();
			} catch (WSError e) {
				publishProgress(e);
				this.cancel(true);
			}*/
		}

		private void playlistSearch(){
/*			JamendoGet2Api service = new JamendoGet2ApiImpl();
			String user = mSearchEditText.getText().toString();
			try {
				mPlaylistRemotes = service.getUserPlaylist(user);
				if(mPlaylistRemotes != null){
					PlaylistRemoteAdapter purpleAdapter = new PlaylistRemoteAdapter(SearchActivity.this);				
					purpleAdapter.setList(mPlaylistRemotes);
					mAdapter = purpleAdapter;
					SearchActivity.this.mSearchMode = SearchMode.UserPlaylist;
				}

			} catch (JSONException e) {
				e.printStackTrace();
			} catch (WSError e) {
				publishProgress(e);
				this.cancel(true);
			}
		}*/

	}
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	public void onLocationChanged(Location location) {
		Log.e(TAG,"onLocationChanged called");
		if (location != null){
			double lot = location.getLongitude();//经度
			double lat = location.getLatitude();//纬度
			final int lotInt = (int) (lot * 1000000);
			final int latInt = (int) (lat * 1000000);
			final GeoPoint tmpLocation = new GeoPoint(latInt,lotInt);
			if(!tmpLocation.equals(mCurLocation)){
				Log.e(TAG, "Location changed lot = "+lot+", lat="+lat);
				mCurLocation = tmpLocation;
				mHandler.sendEmptyMessage(MSG_LOCATION_CHANGED);
			}
			mLocationManager.removeUpdates(this);
		}
	}
}
